/**
 * 
 */
package com.cait.dutyfree.dataaccess.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;

import com.cait.dutyfree.action.impl.LoginAction;
import com.cait.dutyfree.dataaccess.UserServiceDAO;
import com.cait.dutyfree.exception.DutyFreeException;
import com.cait.dutyfree.pojo.LoginDetail;
import com.cait.dutyfree.pojo.LoginUser;
import com.cait.dutyfree.pojo.UserEvent;
import com.cait.dutyfree.security.MD5Hash;

/**
 * @author Rasika Kaluwalgoda
 * 
 */
@Transactional
public class UserServiceDAOImpl extends HibernateDaoSupport implements
		UserServiceDAO {

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#userAuthentication(java.lang
	 * .String, java.lang.String)
	 */

	private static final Logger logger = Logger.getLogger(LoginAction.class);

	public String userAuthentication(String username, String password)
			throws Exception {

		LoginUser user = null;
		DetachedCriteria criteria = DetachedCriteria.forClass(LoginUser.class);
		criteria.add(Restrictions.eq("username", username));
		criteria.add(Restrictions.eq("password",
				MD5Hash.getHashedPassword(password)));

		try {
			@SuppressWarnings("rawtypes")
			List users = getHibernateTemplate().findByCriteria(criteria);
			if ((users != null) && (users.size() > 0)) {
				user = (LoginUser) users.get(0);
				if (user.getFailedLoginAttempts() > 3) {
					logger.warn("Blocked user attempt " + username);
					return "block";
				} else if (user.getStatus() == -1) {
					return "pending";
				} else if (user.getStatus() == 1) {
					return "block";
				} else if (user.getStatus() == 2) {
					return "deactivate";
				} else {
					resetFailLoginAttempts(user);
					return "sucess";
				}

			} else {
				increaseFailLoginAttempts(user);
				return "fail";
			}
		} catch (Exception e) {
			System.out.println(e);
			return "error";
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#addUser(com.cait.dutyfree
	 * .pojo.LoginUser)
	 */
	public boolean addUser(LoginUser user) throws Exception {

		try {
			if (!isUserAvailable(user.getUsername())) {
				getHibernateTemplate().save(user);
				getHibernateTemplate().flush();
				return true;
			} else {
				logger.warn("user already available " + user.getUsername());
				throw new DutyFreeException(1001, new Exception(
						"User Already Available"));
			}
		} catch (Exception e) {
			throw new DutyFreeException(1002, e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#updateUser(com.cait.dutyfree
	 * .pojo.LoginUser)
	 */
	public boolean updateUser(LoginUser user) throws Exception {
		try {
			if (isUserAvailable(user.getUsername())) {
				getHibernateTemplate().merge(user);
				getHibernateTemplate().flush();
				return true;
			} else {
				logger.warn("user not available " + user.getUsername());
				throw new DutyFreeException(1002, new Exception(
						"User not available"));
			}
		} catch (Exception e) {
			throw new DutyFreeException(1002, e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#resetFailLoginAttempts(com
	 * .cait.dutyfree.pojo.LoginUser)
	 */
	public String resetFailLoginAttempts(LoginUser user) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.cait.dutyfree.dataaccess.UserServiceDAO#getUsers()
	 */
	public ArrayList<LoginUser> getUsers() throws Exception {
		try {
			ArrayList<LoginUser> users = new ArrayList<LoginUser>();
			DetachedCriteria criteria = DetachedCriteria
					.forClass(LoginUser.class);
			@SuppressWarnings("rawtypes")
			List userList = getHibernateTemplate().findByCriteria(criteria);
			if ((userList != null) && (userList.size() > 0)) {
				for (int i = 0; i < userList.size(); i++) {
					users.add((LoginUser) userList.get(i));

				}
				return users;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch all users ");
			throw new DutyFreeException(1003, new Exception(
					"During fetch all users"));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.cait.dutyfree.dataaccess.UserServiceDAO#getLockedUsers()
	 */
	public ArrayList<LoginUser> getLockedUsers() throws Exception {
		try {
			ArrayList<LoginUser> users = new ArrayList<LoginUser>();
			DetachedCriteria criteria = DetachedCriteria
					.forClass(LoginUser.class);
			criteria.add(Restrictions.eq("failedLoginAttempts", 4));
			@SuppressWarnings("rawtypes")
			List userList = getHibernateTemplate().findByCriteria(criteria);
			if ((userList != null) && (userList.size() > 0)) {
				for (int i = 0; i < userList.size(); i++) {
					users.add((LoginUser) userList.get(i));
				}
				return users;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch locked users ");
			throw new DutyFreeException(1004, new Exception(
					"During fetch locked users"));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#getUser(java.lang.String)
	 */
	public LoginUser getUser(String username) throws Exception {
		try {
			DetachedCriteria criteria = DetachedCriteria
					.forClass(LoginUser.class);
			criteria.add(Restrictions.eq("username", username));
			@SuppressWarnings("rawtypes")
			List users = getHibernateTemplate().findByCriteria(criteria);
			LoginUser user;
			if ((users != null) && (users.size() > 0)) {
				user = (LoginUser) users.get(0);
				return user;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch user by username ");
			throw new DutyFreeException(1005, new Exception(
					"During fetch user by username"));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.cait.dutyfree.dataaccess.UserServiceDAO#getUser(int)
	 */
	public LoginUser getUser(int userID) throws Exception {
		try {
			DetachedCriteria criteria = DetachedCriteria
					.forClass(LoginUser.class);
			criteria.add(Restrictions.eq("userId", userID));
			@SuppressWarnings("rawtypes")
			List users = getHibernateTemplate().findByCriteria(criteria);
			LoginUser user;
			if ((users != null) && (users.size() > 0)) {
				user = (LoginUser) users.get(0);
				return user;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch user by userid ");
			throw new DutyFreeException(1005, new Exception(
					"During fetch user by userid"));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#updateLastLoginDetails(com
	 * .cait.dutyfree.pojo.LoginUser)
	 */
	public boolean updateLastLoginDetails(LoginUser user) throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#getUserByName(java.lang.String
	 * )
	 */
	public LoginUser getUserByName(String name) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#addLoginDetail(com.cait.dutyfree
	 * .pojo.LoginDetail)
	 */
	public String addLoginDetail(LoginDetail detail) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#getDetails(com.cait.dutyfree
	 * .pojo.LoginUser)
	 */
	public ArrayList<LoginDetail> getDetails(LoginUser user) throws Exception {

		try {
			ArrayList<LoginDetail> logs = new ArrayList<LoginDetail>();
			DetachedCriteria criteria = DetachedCriteria
					.forClass(LoginDetail.class);
			criteria.add(Restrictions.eq("user", user));
			@SuppressWarnings("rawtypes")
			List list = getHibernateTemplate().findByCriteria(criteria);
			if ((list != null) && (list.size() > 0)) {
				for (int i = 0; i < list.size(); i++) {
					logs.add((LoginDetail) list.get(i));
				}
				return logs;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch log details by user ");
			throw new DutyFreeException(1004, new Exception(
					"During fetch log details by user "));
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#getDetails(com.cait.dutyfree
	 * .pojo.LoginUser, int, int)
	 */
	public ArrayList<LoginDetail> getDetails(LoginUser user, int pageSize,
			int pageNo) throws Exception {

		try {
			ArrayList<LoginDetail> logs = new ArrayList<LoginDetail>();
			DetachedCriteria criteria = DetachedCriteria
					.forClass(LoginDetail.class);
			criteria.add(Restrictions.eq("user", user));
			// criteria.addOrder(Order.asc("lodID"));
			criteria.getExecutableCriteria(getSession()).setFirstResult(
					pageSize * (pageNo - 1));
			getHibernateTemplate().setMaxResults(pageSize);
			@SuppressWarnings("rawtypes")
			List list = getHibernateTemplate().findByCriteria(criteria);
			getHibernateTemplate().setMaxResults(0);
			if ((list != null) && (list.size() > 0)) {
				for (int i = 0; i < list.size(); i++) {
					logs.add((LoginDetail) list.get(i));
				}
				return logs;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch log details by user with paging");
			throw new DutyFreeException(1004, new Exception(
					"During fetch log details by user with paging"));
		}

	}

	public boolean isUserAvailable(String userName) throws Exception {

		try {
			DetachedCriteria criteria = DetachedCriteria
					.forClass(LoginUser.class);
			criteria.add(Restrictions.eq("username", userName));
			@SuppressWarnings("rawtypes")
			List users = getHibernateTemplate().findByCriteria(criteria);
			if ((users != null) && (users.size() > 0)) {
				return true;
			}
			return false;
		} catch (Exception e) {
			throw e;
			// TODO: handle exception
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#addUserEvent(com.cait.dutyfree
	 * .pojo.UserEvent)
	 */
	public String addUserEvent(UserEvent event) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.cait.dutyfree.dataaccess.UserServiceDAO#getEvents(com.cait.dutyfree
	 * .pojo.LoginUser)
	 */
	public ArrayList<UserEvent> getEvents(LoginUser user) throws Exception {

		try {
			ArrayList<UserEvent> events = new ArrayList<UserEvent>();
			DetachedCriteria criteria = DetachedCriteria
					.forClass(UserEvent.class);
			criteria.add(Restrictions.eq("user", user));
			@SuppressWarnings("rawtypes")
			List list = getHibernateTemplate().findByCriteria(criteria);
			if ((list != null) && (list.size() > 0)) {
				for (int i = 0; i < list.size(); i++) {
					events.add((UserEvent) list.get(i));
				}
				return events;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch user events ");
			throw new DutyFreeException(1004, new Exception(
					"During fetch user events "));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.cait.dutyfree.dataaccess.UserServiceDAO#getAllEvents()
	 */
	public ArrayList<UserEvent> getAllEvents() throws Exception {
		try {
			ArrayList<UserEvent> events = new ArrayList<UserEvent>();
			DetachedCriteria criteria = DetachedCriteria
					.forClass(UserEvent.class);
			@SuppressWarnings("rawtypes")
			List list = getHibernateTemplate().findByCriteria(criteria);
			if ((list != null) && (list.size() > 0)) {
				for (int i = 0; i < list.size(); i++) {
					events.add((UserEvent) list.get(i));
				}
				return events;
			}
			return null;
		} catch (Exception e) {
			logger.warn("During fetch user events ");
			throw new DutyFreeException(1004, new Exception(
					"During fetch user events "));
		}
	}

	private boolean increaseFailLoginAttempts(LoginUser user) {

		user.setFailedLoginAttempts((user.getFailedLoginAttempts() + 1));
		try {
			getHibernateTemplate().update(user);
			getHibernateTemplate().flush();
			return true;
		} catch (Exception e) {
			return false;
		}
	}

}
